package com.dm.cloud.service.impl;

import com.alibaba.nacos.common.utils.CollectionUtils;
import com.alibaba.nacos.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.dm.cloud.api.dto.Department;
import com.dm.cloud.api.service.IDeptService;
import com.dm.cloud.api.vo.DepartmentVo;
import com.dm.cloud.common.R;
import com.dm.cloud.utils.Oauth2Utils;
import com.dm.cloud.dao.DepartmentDao;
import com.dm.cloud.utils.DtoPreOpratrionUtils;
import com.dm.cloud.utils.MysqlLogger;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DeptServiceImpl implements IDeptService {

    @Autowired
    private DepartmentDao departmentDao;

    @Override
    public R createDept(DepartmentVo deptVo) {

        Department dept = new Department();
        BeanUtils.copyProperties(deptVo,dept);

        if(StringUtils.isBlank(deptVo.getName())){
            return R.failure("部门名称不能为空！");
        }

        try{
            //查询部门是否存在
            QueryWrapper<Department> queryWrapper =new QueryWrapper<>();
            queryWrapper.eq("name", deptVo.getName());
            queryWrapper.eq("delete_flag", 0);
            long accounts = departmentDao.selectCount(queryWrapper);
            if(accounts>0){
                return R.failure("该部门已存在！");
            }

            //记录注册时间
            new DtoPreOpratrionUtils<Department>().preInsert(dept);
            departmentDao.insert(dept);
            MysqlLogger.info(String.format("创建部门【%s】！", dept.getName()));
            return R.success();
        }catch (Exception ex){
            log.error(String.format("创建部门【%s】失败！", dept.getName()),ex.getCause());
            return R.failure("系统异常,注册失败！");
        }
    }

    @Override
    @Transactional
    public R updateDept(DepartmentVo deptVo) {
        Department dept = new Department();
        BeanUtils.copyProperties(deptVo,dept);

        //先判断上级部门是不是当前部门的下级部门  即下级部门篡位 先修改下级部门的ID
        if(StringUtils.isNotBlank(deptVo.getParentId())){
            QueryWrapper searcheri = new QueryWrapper();
            searcheri.eq("parent_id",deptVo.getId());
            searcheri.eq("id",deptVo.getParentId());
            searcheri.eq("delete_flag",0);
            if(departmentDao.selectCount(searcheri)>0){
                //下级部门篡位
                Department cuDept = departmentDao.selectById(deptVo.getId());
                String papaId= cuDept.getParentId();
                Department lowUp = new Department();
                lowUp.setId(Integer.valueOf(deptVo.getParentId()));
                lowUp.setParentId(papaId);
                departmentDao.updateById(lowUp);
            }
        }
        //初始化更新信息
        new DtoPreOpratrionUtils<Department>().preUpdate(dept);
        if(departmentDao.updateById(dept)>0 && invalidDept(deptVo).getCode() == 0){
            MysqlLogger.info(String.format("修改部门【%s】信息",  dept.getName()));
            return R.success("修改成功！");
        }else{
            log.error(String.format("修改部门【%s】信息失败",dept.getName()));
            return R.failure("修改失败！");
        }
    }

    /**
     * 启用停用前检查节点信息
     * @param deptVo
     * @return
     */
    @Override
    public R checkInvalid(DepartmentVo deptVo) {

        List<String> ids = new ArrayList<>();
        QueryWrapper searcher = new QueryWrapper();

        //部门名称不能重复
        if(StringUtils.isNotBlank(deptVo.getName())){
            QueryWrapper searcheri = new QueryWrapper();
            searcheri.eq("name",deptVo.getName());
            searcheri.eq("delete_flag",0);
            searcheri.ne("id",deptVo.getId());
            if(departmentDao.selectCount(searcheri)>0){
                return R.failure("该部门已存在！");
            }
        }else{
            return R.failure("部门名称不能为空！");
        }

        //判断节点是不是调整了层级结构 上级部门不能是自己或者自己的子部门
        if(StringUtils.isNotBlank(deptVo.getParentId())){
            if(deptVo.getId().toString().equals(deptVo.getParentId())){
                return R.failure("上级部门不能是当前部门！");
            }
        }

        if(deptVo.getStatus() == 0) {
            //禁用 全部下级节点
            getAllDeptNode(ids, deptVo.getId().toString());
            ids.remove(deptVo.getId().toString());
            long count = 0 ;
            if(ids.size()>0) {
                //查询这些节点中还有没有启用的
                searcher.eq("status", 1);
                searcher.in("id", ids);

                count = departmentDao.selectCount(searcher);
            }
            return R.success(count);
        }else{
            //启用 全部上级节点
            getAllParentNode(ids, deptVo.getId().toString());
            ids.remove(deptVo.getId().toString());
            long count = 0 ;
            if(ids.size()>0) {
                //查询这些节点中还有没有停用的
                searcher.eq("status",0);
                searcher.in("id",ids);
                count = departmentDao.selectCount(searcher);
            }
            return R.success(count);
        }
    }

    @Override
    public R invalidDept(DepartmentVo deptVo) {
        String authorization = Oauth2Utils.getAuthorization();
        UserDetails user = Oauth2Utils.getByAuthorization(authorization);

        List<String> ids = new ArrayList<>();

        if(deptVo.getStatus() == 0) {

            getAllDeptNode(ids, deptVo.getId().toString());

            if (CollectionUtils.isNotEmpty(ids)) {
                //停用将停用其所有子部门
                try{
                    departmentDao.invalidByIds(ids, user.getUsername(),0);
                    MysqlLogger.info(String.format("停用部门【%s】",deptVo.getName()));
                }catch (Exception ex){
                    return R.failure("停用状态修改失败！");
                }
            }
            return R.success("停用状态修改成功！");
        }else{
            //启用 将启用全部上级节点
            getAllParentNode(ids, deptVo.getId().toString());

            if (CollectionUtils.isNotEmpty(ids)) {
                //启用将启用其所有上级部门
                try{
                    departmentDao.invalidByIds(ids, user.getUsername(),1);
                    MysqlLogger.info(String.format("启用部门【%s】",deptVo.getName()));
                }catch (Exception ex){
                    return R.failure("启用状态修改失败！");
                }
            }
            return R.success("启用状态修改成功！");
        }
    }

    @Override
    public R deleteDept(DepartmentVo deptVo) {
        String authorization = Oauth2Utils.getAuthorization();
        List<String> ids = new ArrayList<>();
        getAllDeptNode(ids,deptVo.getId().toString());

        if (CollectionUtils.isNotEmpty(ids)) {
            Department department = new Department();
            department.setDeleteFlag(1);
            new DtoPreOpratrionUtils<Department>().preUpdate(department);

            UpdateWrapper<Department> updateWapper =new UpdateWrapper<>();
            updateWapper.in("id",ids);

            if(departmentDao.update(department,updateWapper)>0){
                MysqlLogger.info(String.format("删除部门信息【%s】",department.getName()));
            }else{
                return R.failure("部门信息删除失败！");
            }
        }
        return R.success("部门信息删除成功！");
    }

    /**
     * 部门查询查询全部
     * 代码里面解析
     * @param deptVo
     * @return
     */
    @Override
    public R selectPage(DepartmentVo deptVo) {
        DepartmentVo resultContainer = new DepartmentVo();
        resultContainer.setType("layout");

        QueryWrapper<Department> usersQueryWrapper = new QueryWrapper<>();
        usersQueryWrapper.eq("delete_flag",0);
        usersQueryWrapper.orderByDesc("update_date");
        List<Department> list = departmentDao.selectList(usersQueryWrapper);

        //名称单独筛选，要把当前名称的筛选出来 还要把上级带出来
        if(CollectionUtils.isNotEmpty(list)){
            List<String> ids = new ArrayList<>();

            //找到实际有用的部门信息
            List<String> likesidList = new ArrayList<>();

            //名称相似的部门ID
            likesidList = list.stream()
                    .filter(e ->{
                        if(StringUtils.isNotBlank(deptVo.getName()) && !e.getName().contains(deptVo.getName())){
                            return false;
                        }
                        if(null != deptVo.getStatus() && e.getStatus() != deptVo.getStatus()){
                            return false;
                        }
                        return true;
                    })
                    .map(e -> e.getId().toString()).collect(Collectors.toList());

            //找到上述部门的所有上级 注意处理重复
            getAllParentNode(ids, likesidList.toArray(new String[0]));
            ids = ids.stream().distinct().collect(Collectors.toList());

            //然后将id在ids内的部门按照关系整理好
            List<String> finalIds = ids;
            list = list.stream().filter(e -> finalIds.contains(e.getId().toString())).collect(Collectors.toList());


            setChildTree(resultContainer,list);
        }

        return R.success(resultContainer.getChildren());
    }

    @Override
    public R searchDept(String id) {
        Department record = departmentDao.selectById(id);

        DepartmentVo result =new DepartmentVo();
        BeanUtils.copyProperties(record,result);
        return R.success(result);
    }

    /**
     * 获取指定部门下的所有部门
     * @param ids
     * @param id
     */
    private void getAllDeptNode(List<String> ids, String... id){

        List<String> idCurrent = Arrays.asList(id);
        ids.addAll(idCurrent);

        //查询有没有子节点
        UpdateWrapper<Department> childUpdateWapper =new UpdateWrapper<>();
        childUpdateWapper.in("parent_id",idCurrent);
        List<Department> childNode = departmentDao.selectList(childUpdateWapper);

        if(CollectionUtils.isNotEmpty(childNode))
        {
            List<String> idsinner = childNode.stream().map(e->e.getId().toString()).collect(Collectors.toList());
            String[] idsArr = idsinner.toArray(new String[0]);
            getAllDeptNode(ids, idsArr);
        }
    }

    /**
     * 获取指定部门下的所有上级 包括自己
     * @param ids
     * @param id
     */
    private void getAllParentNode(List<String> ids, String... id){

        if(null == id) {
            return;
        }

        ids.addAll(Arrays.asList(id));

        //查询当前部门
        UpdateWrapper<Department> childUpdateWapper =new UpdateWrapper<>();
        childUpdateWapper.in("id",id);
        List<Department> current = departmentDao.selectList(childUpdateWapper);

        if(CollectionUtils.isNotEmpty(current))
        {
            List<String> idsinner = current.stream().map(e->e.getParentId()).collect(Collectors.toList());
            String[] idsArr = idsinner.toArray(new String[0]);
            getAllParentNode(ids, idsArr);
        }
    }

    /**
     * 整理部门树信息
     * @param result
     * @param depts
     */
    private void setChildTree(DepartmentVo result, List<Department> depts){

        if(result == null || CollectionUtils.isEmpty(result.getChildren())){
            //先初始化 在循环
            String currentId = "" ;

            //判断是不是根节点
            if(!"layout".equals(result.getType())){
                currentId = result.getId().toString();
            }

            String finalCurrentId = currentId;
            result.setChildren(depts.stream()
                    .map(e->{
                        if(StringUtils.isBlank(e.getParentId())){
                            e.setParentId("");
                        }
                        return e;
                    }).filter(e-> finalCurrentId.equals(e.getParentId()))
                    .map(e->{
                        DepartmentVo deptVo = new DepartmentVo();
                        BeanUtils.copyProperties(e,deptVo);
                        return deptVo;
                    }).sorted(new Comparator<DepartmentVo>() {
                        @Override
                        public int compare(DepartmentVo o1, DepartmentVo o2) {
                            return o1.getSortNumber().compareTo(o2.getSortNumber());
                        }
                    }).collect(Collectors.toList()));

            if(CollectionUtils.isEmpty(result.getChildren())){
                return;
            }
            setChildTree(result,depts);
        }else{
            for (DepartmentVo departmentVo : result.getChildren()) {
                setChildTree(departmentVo,depts);
            }
        }
    }

}
